<!DOCTYPE HTML>
<!--
	Dimension by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
 <head>
  <title>
   Dimension by HTML5 UP
  </title>
  <!-- <meta charset="utf-8" /> -->
  <!-- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> -->
  <meta charset="utf-8"/>
  <meta content="width=device-width,initial-scale=1.0" name="viewport"/>
  <link href="../../assets/css/article.css" rel="stylesheet"/>
  <link href="https://cdn.bootcss.com/highlight.js/9.15.8/styles/github.min.css" rel="stylesheet"/>
  <noscript>
   <link href="../../assets/css/noscript.css" rel="stylesheet"/>
  </noscript>
 </head>
 <body>
  <div id="app">
  </div>
  <!-- built files will be auto injected -->
 </body>
 <body class="is-preload">
  <!-- Wrapper -->
  <div id="wrapper">
   <!-- Main -->
   <div id="main">
    <article id="article">
     <h1 id="soul-bootstrap">
      Soul网关源码解析（十二）数据同步初探-Bootstrap端
     </h1>
     <hr/>
     <h2 id="_1">
      简介
     </h2>
     <p>
      此篇开始进入分析Soul网关的数据同步相关源码，首先看下数据是哪些数据，同步大致原理和方式
     </p>
     <h2 id="debug">
      源码Debug
     </h2>
     <p>
      数据这里应该路由相关的数据，在程序中用来进行规则匹配、获取后端服务器真实地址之类的
     </p>
     <p>
      在前面的处理流程的分析中，我们知道进行路由匹配的核心代码如下：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">AbstractSoulPlugin</span> <span class="kd">implements</span> <span class="n">SoulPlugin</span> <span class="p">{</span>
    <span class="p">......</span>
    <span class="kd">public</span> <span class="n">Mono</span><span class="o">&lt;</span><span class="n">Void</span><span class="o">&gt;</span> <span class="nf">execute</span><span class="p">(</span><span class="kd">final</span> <span class="n">ServerWebExchange</span> <span class="n">exchange</span><span class="p">,</span> <span class="kd">final</span> <span class="n">SoulPluginChain</span> <span class="n">chain</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">String</span> <span class="n">pluginName</span> <span class="o">=</span> <span class="n">named</span><span class="p">();</span>
        <span class="c1">// 获取插件配置</span>
        <span class="kd">final</span> <span class="n">PluginData</span> <span class="n">pluginData</span> <span class="o">=</span> <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">obtainPluginData</span><span class="p">(</span><span class="n">pluginName</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">pluginData</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&amp;&amp;</span> <span class="n">pluginData</span><span class="p">.</span><span class="na">getEnabled</span><span class="p">())</span> <span class="p">{</span>
            <span class="c1">// 获取选择器</span>
            <span class="kd">final</span> <span class="n">Collection</span><span class="o">&lt;</span><span class="n">SelectorData</span><span class="o">&gt;</span> <span class="n">selectors</span> <span class="o">=</span> <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">obtainSelectorData</span><span class="p">(</span><span class="n">pluginName</span><span class="p">);</span>
            <span class="p">.......</span>
            <span class="c1">// 获取规则</span>
            <span class="kd">final</span> <span class="n">SelectorData</span> <span class="n">selectorData</span> <span class="o">=</span> <span class="n">matchSelector</span><span class="p">(</span><span class="n">exchange</span><span class="p">,</span> <span class="n">selectors</span><span class="p">);</span>
            <span class="p">.......</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="n">chain</span><span class="p">.</span><span class="na">execute</span><span class="p">(</span><span class="n">exchange</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="p">......</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      从上面可以看出数据大致有三种：插件配置数据、选择器数据、规则数据，这些数据都是从 BaseDataCache中获取的，我们来看看其核心代码：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">BaseDataCache</span> <span class="p">{</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">BaseDataCache</span> <span class="n">INSTANCE</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BaseDataCache</span><span class="p">();</span>

    <span class="cm">/**</span>
<span class="cm">     * pluginName -&gt; PluginData.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">ConcurrentMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">PluginData</span><span class="o">&gt;</span> <span class="n">PLUGIN_MAP</span> <span class="o">=</span> <span class="n">Maps</span><span class="p">.</span><span class="na">newConcurrentMap</span><span class="p">();</span>

    <span class="cm">/**</span>
<span class="cm">     * pluginName -&gt; SelectorData.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">ConcurrentMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">SelectorData</span><span class="o">&gt;&gt;</span> <span class="n">SELECTOR_MAP</span> <span class="o">=</span> <span class="n">Maps</span><span class="p">.</span><span class="na">newConcurrentMap</span><span class="p">();</span>

    <span class="cm">/**</span>
<span class="cm">     * selectorId -&gt; RuleData.</span>
<span class="cm">     */</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">ConcurrentMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">RuleData</span><span class="o">&gt;&gt;</span> <span class="n">RULE_MAP</span> <span class="o">=</span> <span class="n">Maps</span><span class="p">.</span><span class="na">newConcurrentMap</span><span class="p">();</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">cachePluginData</span><span class="p">(</span><span class="kd">final</span> <span class="n">PluginData</span> <span class="n">pluginData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">pluginData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">data</span> <span class="o">-&gt;</span> <span class="n">PLUGIN_MAP</span><span class="p">.</span><span class="na">put</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getName</span><span class="p">(),</span> <span class="n">data</span><span class="p">));</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">removePluginData</span><span class="p">(</span><span class="kd">final</span> <span class="n">PluginData</span> <span class="n">pluginData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">pluginData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">data</span> <span class="o">-&gt;</span> <span class="n">PLUGIN_MAP</span><span class="p">.</span><span class="na">remove</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getName</span><span class="p">()));</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="n">PluginData</span> <span class="nf">obtainPluginData</span><span class="p">(</span><span class="kd">final</span> <span class="n">String</span> <span class="n">pluginName</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">PLUGIN_MAP</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">pluginName</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">cacheSelectData</span><span class="p">(</span><span class="kd">final</span> <span class="n">SelectorData</span> <span class="n">selectorData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">selectorData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="k">this</span><span class="p">::</span><span class="n">selectorAccept</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">removeSelectData</span><span class="p">(</span><span class="kd">final</span> <span class="n">SelectorData</span> <span class="n">selectorData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">selectorData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">data</span> <span class="o">-&gt;</span> <span class="p">{</span>
            <span class="kd">final</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">SelectorData</span><span class="o">&gt;</span> <span class="n">selectorDataList</span> <span class="o">=</span> <span class="n">SELECTOR_MAP</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getPluginName</span><span class="p">());</span>
            <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">selectorDataList</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">list</span> <span class="o">-&gt;</span> <span class="n">list</span><span class="p">.</span><span class="na">removeIf</span><span class="p">(</span><span class="n">e</span> <span class="o">-&gt;</span> <span class="n">e</span><span class="p">.</span><span class="na">getId</span><span class="p">().</span><span class="na">equals</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getId</span><span class="p">())));</span>
        <span class="p">});</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">SelectorData</span><span class="o">&gt;</span> <span class="nf">obtainSelectorData</span><span class="p">(</span><span class="kd">final</span> <span class="n">String</span> <span class="n">pluginName</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">SELECTOR_MAP</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">pluginName</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">cacheRuleData</span><span class="p">(</span><span class="kd">final</span> <span class="n">RuleData</span> <span class="n">ruleData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">ruleData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="k">this</span><span class="p">::</span><span class="n">ruleAccept</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">removeRuleData</span><span class="p">(</span><span class="kd">final</span> <span class="n">RuleData</span> <span class="n">ruleData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">ruleData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">data</span> <span class="o">-&gt;</span> <span class="p">{</span>
            <span class="kd">final</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">RuleData</span><span class="o">&gt;</span> <span class="n">ruleDataList</span> <span class="o">=</span> <span class="n">RULE_MAP</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getSelectorId</span><span class="p">());</span>
            <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">ruleDataList</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">list</span> <span class="o">-&gt;</span> <span class="n">list</span><span class="p">.</span><span class="na">removeIf</span><span class="p">(</span><span class="n">rule</span> <span class="o">-&gt;</span> <span class="n">rule</span><span class="p">.</span><span class="na">getId</span><span class="p">().</span><span class="na">equals</span><span class="p">(</span><span class="n">data</span><span class="p">.</span><span class="na">getId</span><span class="p">())));</span>
        <span class="p">});</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">RuleData</span><span class="o">&gt;</span> <span class="nf">obtainRuleData</span><span class="p">(</span><span class="kd">final</span> <span class="n">String</span> <span class="n">selectorId</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">RULE_MAP</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">selectorId</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      从上面的代码可以看出，这是一个静态单例类，从各个方法的名字大致可以看出基本都是对插件配置数据、选择器配置数据、规则配置数据进行的增删改查
     </p>
     <p>
      其中明显的可以看出 cachexxxx , removexxxx 就是对应的更新（增加和修改对map来说一样的操作）和删除操作
     </p>
     <p>
      下面我们来看下， cachexxx、removexxxxx 的方法被哪些地方进行了引用
     </p>
     <p>
      我们使用IDEA，Alt+F7 查看用那些地方进行了使用，通篇查找下来，处理 BaseDataCache类本身和一些测试相关的类，只有CommonPluginDataSubscriber这个类进行了调用，那这个类就是数据同步的核心类了，大致代码如下：
     </p>
     <div class="codehilite">
      <pre><span></span><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CommonPluginDataSubscriber</span> <span class="kd">implements</span> <span class="n">PluginDataSubscriber</span> <span class="p">{</span>
    <span class="p">.......</span>

    <span class="c1">// 下面这类函数又进行了一次封装，我们可以看到这里有那么一点小瑕疵，命名有点不统一；onSubscribe这个函数取的不是太好，不能见名识意，有点宽泛了</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">PluginData</span> <span class="n">pluginData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">pluginData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">unSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">PluginData</span> <span class="n">pluginData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">pluginData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onSelectorSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">SelectorData</span> <span class="n">selectorData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">selectorData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">unSelectorSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">SelectorData</span> <span class="n">selectorData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">selectorData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onRuleSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">RuleData</span> <span class="n">ruleData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">ruleData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">unRuleSubscribe</span><span class="p">(</span><span class="kd">final</span> <span class="n">RuleData</span> <span class="n">ruleData</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">subscribeDataHandler</span><span class="p">(</span><span class="n">ruleData</span><span class="p">,</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">private</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">subscribeDataHandler</span><span class="p">(</span><span class="kd">final</span> <span class="n">T</span> <span class="n">classData</span><span class="p">,</span> <span class="kd">final</span> <span class="n">DataEventTypeEnum</span> <span class="n">dataType</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">classData</span><span class="p">).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">data</span> <span class="o">-&gt;</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">data</span> <span class="k">instanceof</span> <span class="n">PluginData</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">PluginData</span> <span class="n">pluginData</span> <span class="o">=</span> <span class="p">(</span><span class="n">PluginData</span><span class="p">)</span> <span class="n">data</span><span class="p">;</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 插件配置数据的更新</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">cachePluginData</span><span class="p">(</span><span class="n">pluginData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">pluginData</span><span class="p">.</span><span class="na">getName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">handlerPlugin</span><span class="p">(</span><span class="n">pluginData</span><span class="p">));</span>
                <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 插件配置数据的删除</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">removePluginData</span><span class="p">(</span><span class="n">pluginData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">pluginData</span><span class="p">.</span><span class="na">getName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">removePlugin</span><span class="p">(</span><span class="n">pluginData</span><span class="p">));</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">data</span> <span class="k">instanceof</span> <span class="n">SelectorData</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">SelectorData</span> <span class="n">selectorData</span> <span class="o">=</span> <span class="p">(</span><span class="n">SelectorData</span><span class="p">)</span> <span class="n">data</span><span class="p">;</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 选择器数据的更新</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">cacheSelectData</span><span class="p">(</span><span class="n">selectorData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">selectorData</span><span class="p">.</span><span class="na">getPluginName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">handlerSelector</span><span class="p">(</span><span class="n">selectorData</span><span class="p">));</span>
                <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 选择器数据的删除</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">removeSelectData</span><span class="p">(</span><span class="n">selectorData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">selectorData</span><span class="p">.</span><span class="na">getPluginName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">removeSelector</span><span class="p">(</span><span class="n">selectorData</span><span class="p">));</span>
                <span class="p">}</span>
            <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">data</span> <span class="k">instanceof</span> <span class="n">RuleData</span><span class="p">)</span> <span class="p">{</span>
                <span class="n">RuleData</span> <span class="n">ruleData</span> <span class="o">=</span> <span class="p">(</span><span class="n">RuleData</span><span class="p">)</span> <span class="n">data</span><span class="p">;</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">UPDATE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 规则数据的更新</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">cacheRuleData</span><span class="p">(</span><span class="n">ruleData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">ruleData</span><span class="p">.</span><span class="na">getPluginName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">handlerRule</span><span class="p">(</span><span class="n">ruleData</span><span class="p">));</span>
                <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">dataType</span> <span class="o">==</span> <span class="n">DataEventTypeEnum</span><span class="p">.</span><span class="na">DELETE</span><span class="p">)</span> <span class="p">{</span>
                    <span class="c1">// 规则数据的删除</span>
                    <span class="n">BaseDataCache</span><span class="p">.</span><span class="na">getInstance</span><span class="p">().</span><span class="na">removeRuleData</span><span class="p">(</span><span class="n">ruleData</span><span class="p">);</span>
                    <span class="n">Optional</span><span class="p">.</span><span class="na">ofNullable</span><span class="p">(</span><span class="n">handlerMap</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">ruleData</span><span class="p">.</span><span class="na">getPluginName</span><span class="p">())).</span><span class="na">ifPresent</span><span class="p">(</span><span class="n">handler</span> <span class="o">-&gt;</span> <span class="n">handler</span><span class="p">.</span><span class="na">removeRule</span><span class="p">(</span><span class="n">ruleData</span><span class="p">));</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">});</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre>
     </div>
     <p>
      在上面的代码中，我们看它又对相关数据的更新做了一层封装，在其中我们找到一点命名不是太好的地方
     </p>
     <p>
      下面我们来看下这些：onSelectorSubscribe 之类的函数在什么地方被调用了，通过Alt+F7发现（排查测试类和本身），有下面的三个模块进行引用：
     </p>
     <ul>
      <li>
       soul-sync-data-http : PluginDataRefresh
      </li>
      <li>
       soul-sync-data-nacos : NacosCacheHandler
      </li>
      <li>
       soul-sync-data-websocket : PluginDataHandler
      </li>
      <li>
       soul-sync-data-zookeeper : ZookeeperSyncDataService
      </li>
     </ul>
     <p>
      结合前面的了解，可以看到是四大同步方式模块：HTTP、Nacos、websocket、zookeeper
     </p>
     <p>
      大致浏览了一下，这思路同步模块的代码差异比较大，那就是四篇的分析文章了啊
     </p>
     <h2 id="_2">
      总结
     </h2>
     <p>
      此篇文章大致梳理了数据同步比较基础的类：
     </p>
     <ul>
      <li>
       BaseDataCache : 配置缓存，提供更新、删除、查询
      </li>
      <li>
       CommonPluginDataSubscriber : 对BaseDataCache的封装，提供更新和删除
      </li>
      <li>
       同步模块：调用CommonPluginDataSubscriber的接口进行数据同步
       <ul>
        <li>
         soul-sync-data-http : PluginDataRefresh
        </li>
        <li>
         soul-sync-data-nacos : NacosCacheHandler
        </li>
        <li>
         soul-sync-data-websocket : PluginDataHandler
        </li>
        <li>
         soul-sync-data-zookeeper : ZookeeperSyncDataService
        </li>
       </ul>
      </li>
     </ul>
     <p>
      此篇文章先对数据同步有个大致的了解，下面的文章开始进行四大同步模块的分析
     </p>
     <h2 id="soul">
      Soul网关源码分析文章列表
     </h2>
     <h3 id="github">
      Github
     </h3>
     <ul>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB1-%E6%A6%82%E8%A7%88.md">
        Soul源码阅读（一） 概览
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB2-%E5%88%9D%E6%AD%A5%E8%BF%90%E8%A1%8C.md">
        Soul源码阅读（二）代码初步运行
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB3-%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E6%A6%82%E8%A7%88.md">
        Soul源码阅读（三）HTTP请求处理概览
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB4-dubbo%E8%AF%B7%E6%B1%82%E6%A6%82%E8%A7%88.md">
        Soul网关源码阅读（四）Dubbo请求概览
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB5-%E8%AF%B7%E6%B1%82%E7%B1%BB%E5%9E%8B%E6%8E%A2%E7%B4%A2.md">
        Soul网关源码阅读（五）请求类型探索
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB6-sofa%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E6%A6%82%E8%A7%88.md">
        Soul网关源码阅读（六）Sofa请求处理概览
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB7-%E9%99%90%E6%B5%81%E6%8F%92%E4%BB%B6%E5%88%9D%E6%8E%A2.md">
        Soul网关源码阅读（七）限流插件初探
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/0e6931519a84d5c603504b2c6a633698ac793b70/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB8-%E8%B7%AF%E7%94%B1%E5%8C%B9%E9%85%8D%E5%88%9D%E6%8E%A2.md">
        Soul网关源码阅读（八）路由匹配初探
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB9-%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE%E5%8A%A0%E8%BD%BD%E5%88%9D%E6%8E%A2.md">
        Soul网关源码阅读（九）插件配置加载初探
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB10-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AE%80%E5%8D%95%E6%8F%92%E4%BB%B6%E7%BC%96%E5%86%99.md">
        Soul网关源码阅读（十）自定义简单插件编写
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB11-%E8%AF%B7%E6%B1%82%E5%A4%84%E7%90%86%E5%B0%8F%E7%BB%93.md">
        Soul网关源码阅读（十一）请求处理小结
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB12-%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E5%88%9D%E6%8E%A2.md">
        Soul网关源码阅读（十二）数据同步初探-Bootstrap端
       </a>
      </li>
      <li>
       <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB13-websocket%E5%90%8C%E6%AD%A5%E6%95%B0%E6%8D%AE-Bootstrap%E7%AB%AF.md">
        Soul网关源码阅读（十三）Websocket同步数据-Bootstrap端
       </a>
      </li>
      <li>
       <p>
        <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB14-HTTP%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5-Bootstrap%E7%AB%AF.md">
         Soul网关源码阅读（十四）HTTP数据同步-Bootstrap端
        </a>
       </p>
      </li>
      <li>
       <p>
        <a href="https://github.com/lw1243925457/SE-Notes/blob/master/profession/program/%E5%BC%80%E6%BA%90/soul/soul%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E7%95%AA%E5%A4%96%E7%AF%871-HTTP%E7%A4%BA%E4%BE%8B%E5%8F%82%E6%95%B0%E8%AF%B7%E6%B1%82%E9%94%99%E8%AF%AF.md">
         Soul网关源码阅读番外篇（一） HTTP参数请求错误
        </a>
       </p>
      </li>
     </ul>
     <h3 id="_3">
      掘金
     </h3>
     <ul>
      <li>
       <a href="https://juejin.cn/post/6917864624423436296">
        Soul网关源码阅读（一） 概览
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6917865804121767944">
        Soul网关源码阅读（二）代码初步运行
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6917866538712334343">
        Soul网关源码阅读（三）请求处理概览
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6917867369909977102">
        Soul网关源码阅读（四）Dubbo请求概览
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6918575905962983438">
        Soul网关源码阅读（五）请求类型探索
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6918736260467015693">
        Soul网关源码阅读（六）Sofa请求处理概览
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6919348164944232455/">
        Soul网关源码阅读（七）限流插件初探
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6919774553241550855/">
        Soul网关源码阅读（八）路由匹配初探
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6920074307590684685/">
        Soul网关源码阅读（九）插件配置加载初探
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6920142348617777166">
        Soul网关源码阅读（十）自定义简单插件编写
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6920596034171174925">
        Soul网关源码阅读（十一）请求处理小结
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6920596173925384206">
        Soul网关源码阅读（十二）数据同步初探
       </a>
      </li>
      <li>
       <a href="https://juejin.cn/post/6920596028505178125">
        Soul网关源码阅读（十三）Websocket同步数据-Bootstrap端
       </a>
      </li>
      <li>
       <p>
        <a href="https://juejin.cn/post/6920597298674302983">
         Soul网关源码阅读（十四）HTTP数据同步-Bootstrap端
        </a>
       </p>
      </li>
      <li>
       <p>
        <a href="https://juejin.cn/post/6918947689564471309">
         Soul网关源码阅读番外篇（一） HTTP参数请求错误
        </a>
       </p>
      </li>
     </ul>
    </article>
   </div>
   <!-- Footer -->
   <footer id="footer">
    <p class="copyright">
     © Untitled. Design:
     <a href="https://html5up.net">
      HTML5 UP
     </a>
     .
    </p>
   </footer>
  </div>
  <!-- BG -->
  <div id="bg">
  </div>
  <!-- Scripts -->
  <script src="../assets/js/jquery.min.js">
  </script>
  <script src="../assets/js/browser.min.js">
  </script>
  <script src="../assets/js/breakpoints.min.js">
  </script>
  <script src="../assets/js/util.js">
  </script>
  <script src="../assets/js/main.js">
  </script>
 </body>
</html>
